<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
    <title>Context Menu for Map and Graphics</title>

    <link rel="stylesheet" href= "https://js.arcgis.com/3.17/dijit/themes/claro/claro.css">
    <link rel="stylesheet" href="https://js.arcgis.com/3.17/esri/css/esri.css">
    <style>
      html, body {
        height:100%;
        margin: 0;
        padding: 0;
        width:100%;
        overflow:hidden;
      }
      #header {
        overflow:hidden;
        height: 1.6em;
      }
      div.insetType {
        color: #97F900;
        font-size: 24px;
        font-family: Rockwell, Georgia, "Times New Roman", Times, serif;
        padding-left: 25px;
      }
    </style>

    <script src="https://js.arcgis.com/3.17/"></script>
    <script>
      var map, editToolbar, ctxMenuForGraphics, ctxMenuForMap;
      var selected, currentLocation;
      
      require([
        "esri/map", "esri/geometry/Point", "esri/geometry/Polygon", 
        "esri/toolbars/draw", "esri/toolbars/edit",
        "esri/symbols/SimpleMarkerSymbol", "esri/symbols/SimpleLineSymbol",
        "esri/symbols/SimpleFillSymbol",
        "esri/graphic", "esri/geometry/jsonUtils",
        "esri/Color", "dojo/parser",
        "dijit/Menu", "dijit/MenuItem", "dijit/MenuSeparator",
        
        "dijit/form/Button", "dijit/layout/BorderContainer", "dijit/layout/ContentPane", 
        "dojo/domReady!"
      ], function(
        Map, Point, Polygon, 
        Draw, Edit,
        SimpleMarkerSymbol, SimpleLineSymbol, 
        SimpleFillSymbol,
        Graphic, geometryJsonUtils,
        Color, parser,
        Menu, MenuItem, MenuSeparator
      ) {
        parser.parse();

        map = new Map("map", {
          basemap: "satellite",
          center: [20.039, 62.739],
          zoom: 3
        });
        map.on("load", createToolbarAndContextMenu);

        function createToolbarAndContextMenu() {
          // Add some graphics to the map
          addGraphics();

          // Create and setup editing tools
          editToolbar = new Edit(map);

          map.on("click", function(evt) {
            editToolbar.deactivate();
          });

          createMapMenu();
          createGraphicsMenu();
        }

        function createMapMenu() {
          // Creates right-click context menu for map
          ctxMenuForMap = new Menu({
            onOpen: function(box) {
              // Lets calculate the map coordinates where user right clicked.
              // We'll use this to create the graphic when the user clicks
              // on the menu item to "Add Point"
              currentLocation = getMapPointFromMenuPosition(box);          
              editToolbar.deactivate();
            }
          });

          ctxMenuForMap.addChild(new MenuItem({ 
            label: "Add Point",
            onClick: function(evt) {
              var symbol = new SimpleMarkerSymbol(
                SimpleMarkerSymbol.STYLE_SQUARE, 
                30, 
                new SimpleLineSymbol(
                  SimpleLineSymbol.STYLE_SOLID, 
                  new Color([200,235, 254, 0.9]), 
                  2
                ), new Color([200, 235, 254, 0.5]));
              var graphic = new Graphic(geometryJsonUtils.fromJson(currentLocation.toJson()), symbol);
              map.graphics.add(graphic);
            }
          }));

          ctxMenuForMap.startup();
          ctxMenuForMap.bindDomNode(map.container);
        }

        function createGraphicsMenu() {
          // Creates right-click context menu for GRAPHICS
          ctxMenuForGraphics = new Menu({});
          ctxMenuForGraphics.addChild(new MenuItem({ 
            label: "Edit",
            onClick: function() {
              if ( selected.geometry.type !== "point" ) {
                editToolbar.activate(Edit.EDIT_VERTICES, selected);
              } else {
                alert("Not implemented");
              }
            } 
          }));

          ctxMenuForGraphics.addChild(new MenuItem({ 
            label: "Move",
            onClick: function() {
              editToolbar.activate(Edit.MOVE, selected);
            } 
          }));

          ctxMenuForGraphics.addChild(new MenuItem({ 
            label: "Rotate/Scale",
            onClick: function() {
            if ( selected.geometry.type !== "point" ) {
                editToolbar.activate(Edit.ROTATE | Edit.SCALE, selected);
              } else {
                alert("Not implemented");
              }
            }
          }));

          ctxMenuForGraphics.addChild(new MenuItem({ 
            label: "Style",
            onClick: function() {
              alert("Not implemented");
            }
          }));
        
          ctxMenuForGraphics.addChild(new MenuSeparator());
          ctxMenuForGraphics.addChild(new MenuItem({ 
            label: "Delete",
            onClick: function() {
              map.graphics.remove(selected);
            }
          }));

          ctxMenuForGraphics.startup();

          map.graphics.on("mouse-over", function(evt) {
            // We'll use this "selected" graphic to enable editing tools
            // on this graphic when the user click on one of the tools
            // listed in the menu.
            selected = evt.graphic;

            // Let's bind to the graphic underneath the mouse cursor           
            ctxMenuForGraphics.bindDomNode(evt.graphic.getDojoShape().getNode());
          });

          map.graphics.on("mouse-out", function(evt) {
            ctxMenuForGraphics.unBindDomNode(evt.graphic.getDojoShape().getNode());
          });
        }

        // Helper Methods
        function getMapPointFromMenuPosition(box) {
          var x = box.x, y = box.y;
          switch( box.corner ) {
            case "TR":
              x += box.w;
              break;
            case "BL":
              y += box.h;
              break;
            case "BR":
              x += box.w;
              y += box.h;
              break;
          }

          var screenPoint = new Point(x - map.position.x, y - map.position.y);
          return map.toMap(screenPoint);
        }
        
        function addGraphics() {
          // Adds pre-defined geometries to map
          var polygonSymbol = new SimpleFillSymbol(
            SimpleFillSymbol.STYLE_SOLID, 
            new SimpleLineSymbol(
              SimpleLineSymbol.STYLE_DOT, 
              new Color([151, 249, 0, 0.8]),
              3
            ), 
            new Color([151, 249, 0, 0.45])
          );
          
          var polygon = new Polygon({
            "rings": [
              [
                [-4226661.916056009, 8496372.808143634],
                [-3835304.3312360067, 8731187.359035634],
                [-2269873.991956003, 9005137.668409634],
                [-1213208.5129420012, 8613780.083589634],
                [-1017529.7205320001, 8065879.464841632],
                [-1213208.5129420012, 7478843.087611631],
                [-2230738.233474003, 6891806.710381631],
                [-2935181.8861500043, 6735263.6764536295],
                [-3522218.263380006, 6891806.710381631],
                [-3952711.606682008, 7165757.01975563],
                [-4265797.674538009, 7283164.295201631],
                [-4304933.433020009, 7635386.121539632],
                [-4304933.433020009, 7674521.880021632],
                [-4226661.916056009, 8496372.808143634]
              ]
            ],
            "spatialReference": {
              "wkid": 102100
            }
          });
          var arrow = new Polygon({
            "rings": [
              [
                [9862211.137464028, 6617856.40100763],
                [8922952.933896024, 5522055.163511626],
                [8922952.933896024, 5991684.265295628],
                [6105178.323192019, 5991684.265295628],
                [6105178.323192019, 7087485.50279163],
                [8922952.933896024, 7087485.50279163],
                [8922952.933896024, 7557114.604575632],
                [9862211.137464028, 6617856.40100763]
              ]
            ],
            "spatialReference": {
              "wkid": 102100
            }
          });

          var triangle = new Polygon({
            "rings": [
              [
                [2426417.02588401, 8535508.566625634],
                [4304933.433020014, 12292541.380897645],
                [6183449.840156019, 8535508.566625634],
                [2426417.02588401, 8535508.566625634]
              ]
            ],
            "spatialReference": {
              "wkid": 102100
            }
          });

          map.graphics.add(new Graphic(polygon, polygonSymbol));
          map.graphics.add(new Graphic(arrow, polygonSymbol));
          map.graphics.add(new Graphic(triangle, polygonSymbol));
        }
      });
    </script>
  </head>
  <body class="claro" style="font-size: 0.75em;">
    <div data-dojo-type="dijit/layout/BorderContainer" 
         data-dojo-props="design:'headline', gutters:false" 
         style="width:100%;height:100%;">

      <div id="header" 
            data-dojo-type="dijit/layout/ContentPane" 
            data-dojo-props="region:'top'"> 

        <div class="insetType">Right-click on map or graphic to view context menu</div>

      </div>

      <div id="map" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'" ></div>

    </div>
  </body>
</html>
